package kr.co.hk.local;

import java.util.ArrayList;
import java.util.Iterator;

import kr.co.hk.R;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Point;
import android.graphics.RectF;
import android.graphics.Paint.Style;
import android.graphics.drawable.Drawable;
import com.google.android.maps.GeoPoint;
import com.google.android.maps.ItemizedOverlay;
import com.google.android.maps.MapView;
import com.google.android.maps.OverlayItem;

public class LocalItemizedOverlay extends ItemizedOverlay<OverlayItem> {
	private ArrayList<OverlayItem> list = new ArrayList<OverlayItem>();
	private ArrayList<LocalInfo> list_info = new ArrayList<LocalInfo>();
	private ArrayList<LocalInfo> my_info = new ArrayList<LocalInfo>();
	private Context mContext;
	private Bitmap bubbleIcon, shadowIcon, markerIcon;
	private Paint innerPaint, borderPaint, textPaint;
	MapView map;
	OverlayItem item;
	LocalInfo localInfo;
	private LocalInfo selectedMapLocation;

	public LocalItemizedOverlay(Drawable defaultMarker) {
		super(defaultMarker);
	}

	public void addOverlay(OverlayItem overlay) {
		list.add(overlay);
		populate();
	}

	public void addList(LocalInfo li) {
		list_info.add(li);
		populate();
	}

	public void addMy(LocalInfo li) {
		my_info.add(li);
		populate();
	}

	@Override
	protected OverlayItem createItem(int index) {
		return list.get(index);
	}

	@Override
	public int size() {
		return list.size();
	}

	public LocalItemizedOverlay(Drawable defaultMarker, Context context,
			MapView mapView, GeoPoint tapPoint) {
		super(defaultMarker);

		mContext = context;
		map = mapView;
		bubbleIcon = BitmapFactory.decodeResource(context.getResources(),
				R.drawable.bubble);
		shadowIcon = BitmapFactory.decodeResource(context.getResources(),
				R.drawable.shadow);

		markerIcon = BitmapFactory.decodeResource(context.getResources(),
				R.drawable.ic_menu_myplaces);

		textPaint = getTextPaint();
		RectF hitTestRecr = new RectF();
		Point screenCoords = new Point();
		mapView.getProjection().toPixels(tapPoint, screenCoords);

		hitTestRecr.set(-bubbleIcon.getWidth() / 2, -bubbleIcon.getHeight(),
				bubbleIcon.getWidth() / 2, 0);
		hitTestRecr.offset(screenCoords.x, screenCoords.y);

		mapView.getProjection().toPixels(tapPoint, screenCoords);
	}

	public LocalItemizedOverlay(Drawable defaultMarker, Context context) {

		super(defaultMarker);
		mContext = context;
	}

	@Override
	public boolean onTap(GeoPoint p, MapView mapView) {
		selectedMapLocation = getHitMapLocation(mapView, p);
		if (selectedMapLocation != null) {
			mapView.invalidate();

		}
		return false;
	}

	private LocalInfo getHitMapLocation(MapView mapView, GeoPoint tapPoint) {

		LocalInfo hitMapLocation = null;
		RectF hitTestRecr = new RectF();
		Point screenCoords = new Point();

		if (list_info.size()>0) {
			Iterator<LocalInfo> iterator = list_info.iterator();
			while (iterator.hasNext()) {
				LocalInfo location = iterator.next();

				mapView.getProjection().toPixels(
						new GeoPoint((int) (location.getLocationLat() * 1E6),
								(int) (location.getLocationLng() * 1E6)),
						screenCoords);

				hitTestRecr.set(-bubbleIcon.getWidth() / 2, -bubbleIcon
						.getHeight(), bubbleIcon.getWidth() / 2, 0);
				hitTestRecr.offset(screenCoords.x, screenCoords.y);

				mapView.getProjection().toPixels(tapPoint, screenCoords);
				if (hitTestRecr.contains(screenCoords.x, screenCoords.y)) {
					hitMapLocation = location;
					break;
				}

			}
		}
		if (my_info.size()>0) {
			Iterator<LocalInfo> my_iterator = my_info.iterator();
			if (hitMapLocation == null) {
				while (my_iterator.hasNext()) {
					LocalInfo my_location = my_iterator.next();

					mapView
							.getProjection()
							.toPixels(
									new GeoPoint(
											(int) (my_location.getLocationLat() * 1E6),
											(int) (my_location.getLocationLng() * 1E6)),
									screenCoords);

					hitTestRecr.set(-bubbleIcon.getWidth() / 2, -bubbleIcon
							.getHeight(), bubbleIcon.getWidth() / 2, 0);
					hitTestRecr.offset(screenCoords.x, screenCoords.y);

					mapView.getProjection().toPixels(tapPoint, screenCoords);
					if (hitTestRecr.contains(screenCoords.x, screenCoords.y)) {
						hitMapLocation = my_location;
						break;
					}
				}
			}
		}
		tapPoint = null;

		return hitMapLocation;
	}


	@Override
	public void draw(Canvas canvas, MapView mapView, boolean shadow) {
		drawMapLocations(canvas, mapView, shadow);
		drawInfoWindow(canvas, mapView, shadow);
		drawMyLocations(canvas, mapView, shadow);
	}

	private void drawMapLocations(Canvas canvas, MapView mapView, boolean shadow) {

		Iterator<LocalInfo> iterator = list_info.iterator();
		Point screenCoords = new Point();
		while (iterator.hasNext()) {
			LocalInfo location = iterator.next();
			mapView.getProjection().toPixels(
					new GeoPoint((int) (location.getLocationLat() * 1E6),
							(int) (location.getLocationLng() * 1E6)),
					screenCoords);

			if (shadow) {
				canvas.drawBitmap(shadowIcon, screenCoords.x, screenCoords.y
						- shadowIcon.getHeight(), null);
			} else {
				canvas.drawBitmap(bubbleIcon, screenCoords.x
						- bubbleIcon.getWidth() / 2, screenCoords.y
						- bubbleIcon.getHeight(), null);
			}
		}

	}

	private void drawMyLocations(Canvas canvas, MapView mapView, boolean shadow) {

		Iterator<LocalInfo> iterator = my_info.iterator();
		Point screenCoords = new Point();
		while (iterator.hasNext()) {
			LocalInfo location = iterator.next();
			mapView.getProjection().toPixels(
					new GeoPoint((int) (location.getLocationLat() * 1E6),
							(int) (location.getLocationLng() * 1E6)),
					screenCoords);

			canvas.drawBitmap(markerIcon, screenCoords.x
					- bubbleIcon.getWidth() / 2, screenCoords.y
					- bubbleIcon.getHeight(), null);
		}

	}

	public void mPopulate() {
		populate();
	}

	private void drawInfoWindow(Canvas canvas, MapView mapView, boolean shadow) {
		if (selectedMapLocation != null) {
			if (shadow) {
			} else {
				Point selDestinationOffset = new Point();
				mapView.getProjection()
						.toPixels(
								new GeoPoint((int) (selectedMapLocation
										.getLocationLat() * 1E6),
										(int) (selectedMapLocation
												.getLocationLng() * 1E6)),
								selDestinationOffset);

				int INFO_WINDOW_WIDTH = (int) Math.ceil(textPaint
						.measureText(selectedMapLocation.getTitle()+selectedMapLocation.getDistance())) + 25;
				int INFO_WINDOW_HEIGHT = 25;
				RectF infoWindowRect = new RectF(0, 0, INFO_WINDOW_WIDTH,
						INFO_WINDOW_HEIGHT);
				int infoWindowOffsetX = selDestinationOffset.x
						- INFO_WINDOW_WIDTH / 2;
				int infoWindowOffsetY = selDestinationOffset.y
						- INFO_WINDOW_HEIGHT - bubbleIcon.getHeight();
				infoWindowRect.offset(infoWindowOffsetX, infoWindowOffsetY);

				canvas.drawRoundRect(infoWindowRect, 5, 5, getInnerPaint());

				canvas.drawRoundRect(infoWindowRect, 5, 5, getBorderPaint());

				int TEXT_OFFSET_X = 10;
				int TEXT_OFFSET_Y = 15;
				canvas.drawText(selectedMapLocation.getTitle()+selectedMapLocation.getDistance(),
						infoWindowOffsetX + TEXT_OFFSET_X, infoWindowOffsetY
								+ TEXT_OFFSET_Y, getTextPaint());
			}
		}
	}

	public Paint getInnerPaint() {
		if (innerPaint == null) {
			innerPaint = new Paint();
			innerPaint.setARGB(225, 75, 75, 75); 
			innerPaint.setAntiAlias(true);
		}
		return innerPaint;
	}

	public Paint getBorderPaint() {
		if (borderPaint == null) {
			borderPaint = new Paint();
			borderPaint.setARGB(255, 255, 255, 255);
			borderPaint.setAntiAlias(true);
			borderPaint.setStyle(Style.STROKE);
			borderPaint.setStrokeWidth(2);
		}
		return borderPaint;
	}

	public Paint getTextPaint() {
		if (textPaint == null) {
			textPaint = new Paint();
			textPaint.setARGB(255, 255, 255, 255);
			textPaint.setAntiAlias(true);
			textPaint.setTextSize(17);
		}
		return textPaint;
	}

}
